﻿using Microsoft.EntityFrameworkCore;
using mozhi.smarterp.Finance.EntityFrameworkCore;
using mozhi.smarterp.Finance.Enums;
using mozhi.smarterp.Finance.Querys;
using mozhi.smarterp.Finance.Reports.Repository;
using mozhi.smarterp.Finance.Views;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Guids;

namespace mozhi.smarterp.Finance.Reports
{
    public class FinancialReportItemRepository : EfCoreRepository<FinanceDbContext , FinancialReportItem , Guid>, IFinancialReportItemRepository
    {
        private IGuidGenerator _guidGenerator;

        public FinancialReportItemRepository(IDbContextProvider<FinanceDbContext> dbContextProvider , IGuidGenerator guidGenerator) : base(dbContextProvider)
        {
            _guidGenerator = guidGenerator;
        }

        public async Task<List<FinancialReportItem>> FindAsync(FinancialReportItemQuery query)
        {
            var dbQuery = query.IncludeDetail == true ? DbContext.Set<FinancialReportItem>().Include(x => x.Settings).AsNoTracking() : DbContext.Set<FinancialReportItem>().AsNoTracking();

            var reportItems = await dbQuery
                .WhereIf(!query.Keyword.IsNullOrEmpty(), x => x.Name.Contains(query.Keyword) || (x.Code != null && x.Code.Contains(query.Keyword)))
                .WhereIf(query.Ids != null && query.Ids.Count > 0, x => query.Ids.Contains(x.Id))
                .WhereIf(query.Activated.HasValue, x => x.Activated == query.Activated.Value)
                .WhereIf(query.ExclusionId.HasValue, x => x.Id != query.ExclusionId.Value)
                .WhereIf(query.ReportType != default, x => x.ReportType == query.ReportType)
                .WhereIf(!query.Code.IsNullOrEmpty(), x => x.Code == query.Code)
                .OrderBy(x => x.Index)
                .ToListAsync();

            return reportItems;
        }

        
        public async Task<int> GetCountAsync(FinancialReportItemQuery query)
        {
            var count = await DbContext.Set<FinancialReportItem>().AsNoTracking()
                .WhereIf(!query.Keyword.IsNullOrEmpty(), x => x.Name.Contains(query.Keyword) || (x.Code != null && x.Code.Contains(query.Keyword)))
                .WhereIf(query.Ids != null && query.Ids.Count > 0, x => query.Ids.Contains(x.Id))
                .WhereIf(query.Activated.HasValue, x => x.Activated == query.Activated.Value)
                .WhereIf(query.ExclusionId.HasValue, x => x.Id != query.ExclusionId.Value)
                .WhereIf(query.ReportType != default, x => x.ReportType == query.ReportType)
                .CountAsync();

            return count;
        }

        public async Task<List<FinancialReportItem>> InsertAsync(List<FinancialReportItem> items)
        {
            foreach (var item in items)
            {
                DbContext.Set<FinancialReportItem>().Add(item);
            }

            if (await DbContext.SaveChangesAsync() <= 0)
                return new List<FinancialReportItem>();

            return items;
        }

      
        public async Task DeleteAsync(List<FinancialReportItem> items)
        {
            foreach(var item in items)
            {
                DbContext.Set<FinancialReportItem>().Remove(item);
            }

            await DbContext.SaveChangesAsync();
        }

        public async Task<List<FinancialReportItem>> GetDefaultReportItemsAsync(AccountingStandardType accountingStandard)
        {
            var reportItems = new List<FinancialReportItem>();

            var defaultReportItems = await DbContext.Set<vFinancialReportItem>().AsNoTracking().Where(x => x.AccountStandard == ((int)accountingStandard).ToString()).ToListAsync();

            var defaultReportItemSettings = await DbContext.Set<vFinancialReportItemSetting>().AsNoTracking().Where(x => x.AccountStandard == ((int)accountingStandard).ToString()).ToListAsync();

            foreach (var defaultItem in defaultReportItems)
            {
                var matchDefaultSettings = defaultReportItemSettings.Where(x => x.ReportItemCode == defaultItem.Code).ToList();

                var reportType = int.Parse(defaultItem.ReportType);

                var item = new FinancialReportItem(_guidGenerator.Create(), defaultItem.Code, defaultItem.ParentCode, defaultItem.AssociateCode,
                    (FinancialReportType)reportType, accountingStandard, defaultItem.Number, defaultItem.Name, int.Parse(defaultItem.Index));

                foreach (var defaultSetting in matchDefaultSettings)
                {
                    int? preCondition = defaultSetting.Precondition.IsNullOrEmpty() ? null : int.Parse(defaultSetting.Precondition);

                    var setting = new FinancialReportItemSetting(_guidGenerator.Create(), item.Id, item.Code, 
                        defaultSetting.AccountCode, defaultSetting.Operator, preCondition);

                    item.AddItem(setting);
                }

                reportItems.Add(item);
            }

            return reportItems;
        }
    }
}
